﻿
using TagLib;
using TagLib.Mpeg;
using TagFile = TagLib.File;


namespace KinonekoSoftware.Studio.Utils
{
    public class MusicInfoFileAbstraction : TagFile.IFileAbstraction
    {
        public void CloseStream(Stream stream)
        {
            stream.Close();
        }
        public MemoryStream BufferedStream { get; init; }
        public string       Name           { get; init; }
        public Stream       ReadStream     => BufferedStream;
        public Stream       WriteStream    => BufferedStream;
    }
    
    public class ImageInfoFileAbstraction: TagFile.IFileAbstraction
    {
        public void CloseStream(Stream stream)
        {
            stream.Close();
        }
        public MemoryStream BufferedStream { get; init; }
        public string       Name           { get; init; }
        public Stream       ReadStream     => BufferedStream;
        public Stream       WriteStream    => BufferedStream;
    }
    
    public static class MediaInfo
    {
        private static string CombineString(IReadOnlyList<string> source)
        {
            const string pattern = "{0},{1}";
            if (source is null ||
                source.Count == 0)
            {
                return "Unknown";
            }
            return source.Aggregate((a, b) => string.Format(pattern, a, b));
        }
        
        public static void Read(byte[] buffer, string ext,  out int w, out int h)
        {
            try
            {

                var iifa = new ImageInfoFileAbstraction
                {
                    BufferedStream = new MemoryStream(buffer),
                    Name           = $"temp{ext}",
                };
                var img = TagFile.Create(iifa);
                w = img.Properties.PhotoWidth;
                h = img.Properties.PhotoHeight;
                img.Dispose();
            }
            catch(Exception ex)
            {
                w = -1;
                h = -1;
            }
        }
        
        
        public static void Read(MemoryStream ms, string ext, out int w, out int h)
        {
            try
            {
                ms.Seek(0, SeekOrigin.Begin);
                var iifa = new ImageInfoFileAbstraction
                {
                    BufferedStream = ms,
                    Name           = $"temp{ext}",
                };
                var img = TagFile.Create(iifa);
                w = img.Properties.PhotoWidth;
                h = img.Properties.PhotoHeight;
                img.Dispose();
                ms.Seek(0, SeekOrigin.Begin);
            }
            catch(Exception ex)
            {
                w = -1;
                h = -1;
            }
        }
        
        public static bool Read(string fileName, string fileNameWithoutExtension, byte[] buffer, out string performers, out string title, out byte[] cover, out MusicType type)
        {
            var mifa = new MusicInfoFileAbstraction
            {
                BufferedStream = new MemoryStream(buffer),
                Name           = fileName,
            };
            
            var file = TagFile.Create(mifa);
            type = file.MimeType.EndsWith("wav") ? MusicType.Wav : MusicType.Mp3;
            Tag tag;
            
            if (file is AudioFile mp3)
            {
                tag       = mp3.GetTag(TagTypes.Id3v2); 
            }
            else if (file is TagLib.Riff.File wav)
            {
                tag = wav.GetTag(TagTypes.Id3v2); 
            }
            else
            {
                title  = performers = string.Empty;
                buffer = null;
                cover  = null;
                return false;
            }
            
            if (tag.Pictures is not null &&
                tag.Pictures.Length > 0)
            {
                cover = tag.Pictures[0]
                           .Data
                           .Data;
            }
            else
            {
                cover = null;
            }
            performers = CombineString(tag.Performers);
            title      = string.IsNullOrEmpty(tag.Title) ? fileNameWithoutExtension : tag.Title;
            
            //
            //
            file.Dispose();
            return true;
        }
    }
}